Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: workflow to upload theme directory artifact #39

Merged
merged 1 commit into from
Oct 19, 2023

Conversation

rise-erpelding
Copy link
Contributor

@rise-erpelding rise-erpelding commented Sep 19, 2023

Description

This adds a GitHub Actions workflow that builds a Docker image using the repo's existing Dockerfile

Closes #21

To Validate

  • Check the most recent run of the workflow (before run on PR was disabled) and confirm that it was successful and that it is the product of the most recent SparkPress package (the sha256 on the package tagged latest should match the one at the bottom of the "Build Inventory Image" step of the workflow). Optionally, you can also push a commit to run the workflow on PR and check it from there.
  • The created package should be associated with the repository, you should see it if you click on "Code" from the repo, it should also be visible under "Packages" from github.com/sparkbox and shows that it belongs in sparkbox/sparkpress-wordpress-starter.

Note: You should also be able to pull/run the image but it's kind of a hassle! You'd need to authenticate to the container registry. To run it locally I modified the docker-compose.yml as seen below and ran docker-compose up.

web:
    # build: .
    image: ghcr.io/sparkbox/sparkpress:latest

@rise-erpelding rise-erpelding force-pushed the chore--create-docker-deployment-workflow branch 4 times, most recently from 36f1f78 to 0a9c588 Compare September 22, 2023 19:11
@rise-erpelding rise-erpelding marked this pull request as ready for review September 22, 2023 20:32
Copy link
Member

@jonoliver jonoliver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Rise, this is awesome! 🎉

I think we're almost there...you're successfully building and pushing the docker image, but our production image will need to be built slightly different than our development image.

In our development image, we build all of the WordPress core files into the image, but then we mount our theme and configuration files as volumes when starting the development container via docker compose. This is great for development, because instead of building our source code into the docker image, we can tell the container to read these files from our local disk, meaning that any changes to theme/configuration files do not require a rebuild of the docker image and restart of the container.

However, in our production image, we want to build all of our final template and configuration files into the image itself, so that all of that code is bundled with the image, and it can essentially run self-contained without the need to mount external volumes.

In order to do that, I think we can leverage multi-stage docker builds.

This will involve modifying Dockerfile and docker-compose.yml. Essentially, we'll use our existing steps in our Dockerfile as the first stage of the build, called dev, and then copy our build files into the image in a second stage, called prod.

Updates to Dockerfile

At the top of Dockerfile, we'll add as dev as the build stage name:

FROM php:8.1-apache-buster as dev

This tells docker that all of the subsequent steps are part of the dev stage. Then, at the bottom of the Dockerfile, we can specify a new stage called prod, which uses dev as a base:

FROM dev as prod

After that, we need to add some COPY steps as part of this stage to copy over relevant files into the prod image. For example, to copy the theme files:

COPY theme /var/www/html/wp-content/themes/sparkpress

We can look at the volumes mounted in docker-compose.yml to see which files / folders we need to copy over. I think we'll need corresponding COPY lines for each of these:

  • theme
  • wp-configs/wp-config.php
  • wp-configs/php.ini
  • wp-configs/.htaccess.

Updates to docker-compose.yml

Our docker-compose.yml configuration is currently only used for local development. We can update the build settings so that it only builds the dev stage as a target:

    build:
      context: .
      target: dev

The result is that:

  1. Our development environment runs the same, because it uses docker-compose and only builds the dev part of the image.
  2. Our production build, using docker build . runs both stages of the build, copying the necessary files into the final image that is pushed to Github.

Validation

We can validate this by verifying that:

  • restarting the development environment doesn't break anything
  • Running docker build . --tag ghcr.io/sparkbox/sparkpress:latest locally copies the production files into the image (requires running npm run build:prod first)
  • We can run a container from the production image locally (I will follow up with more details here)

username: ${{github.actor}}
password: ${{secrets.GH_TOKEN}}

- name: 'Build Inventory Image'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool, thanks for figuring this out!

with:
registry: ghcr.io
username: ${{github.actor}}
password: ${{secrets.GH_TOKEN}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this currently using a personal access token that you created?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@rise-erpelding rise-erpelding force-pushed the chore--create-docker-deployment-workflow branch 2 times, most recently from f8d8fba to 3189e6d Compare October 2, 2023 23:54
@jonoliver
Copy link
Member

jonoliver commented Oct 5, 2023

@rise-erpelding let's remove the multistage build and try copying the files directly into the image. We can remove the as dev from the top line, as well as the FROM dev as prod. This should allow the files to be copied into the image the host machine, but requires us to run either npm run build:dev or npm run build:prod first.

@robtarr after our discussion, I thought of one potential issue with this approach. We're using run-p for our npm start script, that could potentially present race conditions, because serve:dev will require assets created by build:dev.

Edit
@rise-erpelding you're right, after removing plugins from .dockerignore the files are copying over!
Adding a note here to check the file permissions as part of #79, since these are all being copied over as root. We don't need to address that here though.

@jonoliver
Copy link
Member

I was able to successfully run the image as a container and run WordPress locally!

  1. Run only the database container so that we have a database to connect to: docker compose up db
  2. Build the theme: npm run build:prod
  3. Build the image: docker build . --tag wordpress-web-base
  4. Copy over your existing .env settings to a new env file to test: cp .env .docker.test.env
  5. In .docker.test.env update this value, so that our container can talk to the running database:
    • MYSQL_HOST=host.docker.internal:3309
  6. Start a web container from the built image
    • docker run -p 4567:80 --rm -v ./.docker.test.env:/var/www/html/.env -v ./uploads:/var/www/html/wp-content/uploads --name wordpress-web wordpress-web-base
  7. Navigate to http://localhost:4567 and walk through WordPress installation instructions

With these steps, I was able to run a container, connect to the database, log into the admin and upload a file to the mounted uploads volume.

@rise-erpelding
Copy link
Contributor Author

@jonoliver I have not been able to follow these instructions to run the container from the image with the database working--I keep getting Error establishing a database connection when I go to localhost:4567. Is this something that needs to be addressed? And if not, would the next step be to run the GitHub action again before merging and confirm that it seems to be doing the right things?

Copy link
Member

@jonoliver jonoliver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rise-erpelding apologies for the delay, following up here. There are a few more updates that I think we should make, then this should be ready to merge.

  • Rename the action to deploy.docker.yml to match the format of deploy.pantheon.yml
  • Add the workflow_dispatch to the action (example here)
  • Add DEPLOY_WITH_DOCKER conditional flag

To answer your questions:

Is this something that needs to be addressed? And if not, would the next step be to run the GitHub action again before merging and confirm that it seems to be doing the right things?

After we make the updates, we can pair to test this via workflow_dispatch to ensure test the deployed image.

Also, we will ultimately need some documentation around this process, but I will create a new issue for that.

.github/workflows/deploy.yml Outdated Show resolved Hide resolved
.github/workflows/deploy.yml Outdated Show resolved Hide resolved
@rise-erpelding rise-erpelding force-pushed the chore--create-docker-deployment-workflow branch from 3c33f69 to 8c6ab93 Compare October 17, 2023 19:50
@rise-erpelding
Copy link
Contributor Author

@jonoliver I ran the workflow, saw a warning about using a deprecated version of node, updated the docker/login-action action and ran again (this is the corresponding run, and this is the image it created), from what I can tell it seems like it's working correctly, what do you think?

@jonoliver
Copy link
Member

@rise-erpelding I tested the image created by the workflow, and was able to successfully run it locally! Here are the updated instructions I used to test. I don't think you need to walk through these steps before merging, but I'm capturing here in case we include any of these steps in a subsequent documentation PR.

  1. Run only the database container so that we have a database to connect to: docker compose up db
  2. Pull down the image: docker pull ghcr.io/sparkbox/sparkpress:latest
  3. Copy over your existing .env settings to a new env file to test: cp .env .docker.test.env
  4. In .docker.test.env update this value, so that our container can talk to the running database:
    • MYSQL_HOST=host.docker.internal:3309
  5. Start a web container from the image
    • docker run -p 8000:80 --rm -v ./.docker.test.env:/var/www/html/.env -v ./uploads:/var/www/html/wp-content/uploads --name wordpress-web ghcr.io/sparkbox/sparkpress:latest
  6. Navigate to http://localhost:8000

@rise-erpelding rise-erpelding force-pushed the chore--create-docker-deployment-workflow branch from 28f9721 to 560ed30 Compare October 19, 2023 20:07

jobs:
deploy:
if: ${{ vars.DEPLOY_WITH_DOCKER }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note in #94 that this is a variable that needs to be set in GitHub

with:
registry: ghcr.io
username: ${{github.actor}}
password: ${{secrets.GH_TOKEN}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note in #94 that this is a secret that needs to be set in GitHub

@rise-erpelding rise-erpelding force-pushed the chore--create-docker-deployment-workflow branch from 560ed30 to 45c98d7 Compare October 19, 2023 20:20
@rise-erpelding rise-erpelding merged commit 45c98d7 into main Oct 19, 2023
1 check passed
@rise-erpelding rise-erpelding deleted the chore--create-docker-deployment-workflow branch October 19, 2023 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create docker deployment workflow
2 participants